﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data.OracleClient;
using System.Data;

namespace MM.Common.DBBase
{
    public class DbOracleData : DbBase
    {
        // Fields
        protected OracleConnection dataConn;
        protected OracleTransaction dbTransaction;

        // Methods
        protected void AddParms(OracleCommand cmd, DataParamCol parms)
        {
            foreach (DataParam param in parms)
            {
                if (param.Value == null)
                {
                    param.Value = DBNull.Value;
                }
                if ((param.Value.GetType().Name == "DateTime") && (((DateTime)param.Value) == DateTime.MinValue))
                {
                    param.Value = DBNull.Value;
                }
                cmd.Parameters.AddWithValue(param.Name, param.Value);
                cmd.Parameters[param.Name].Direction = param.Direction;
                if (param.Size != 0)
                {
                    cmd.Parameters[param.Name].Size = param.Size;
                }
                if (param.Type != null)
                {
                    cmd.Parameters[param.Name].OracleType = this.GetDBType(param.Type);
                }
            }
        }

        protected override bool BeginTransaction()
        {
            base.ClearErrorMessage();
            try
            {
                this.dbTransaction = this.dataConn.BeginTransaction();
                return true;
            }
            catch (Exception exception)
            {
                base.errorMessage.Append(exception.Message);
                return false;
            }
        }

        protected override bool CommitTransaction()
        {
            base.ClearErrorMessage();
            try
            {
                if (this.IsExistTransaction)
                {
                    this.dbTransaction.Commit();
                }
                return true;
            }
            catch (Exception exception)
            {
                base.errorMessage.Append(exception.Message);
                return false;
            }
        }

        public override string DataSource()
        {
            return this.dataConn.DataSource;
        }

        public override void DBClose()
        {
            this.dataConn.Close();
        }

        public override bool ExecuteProcedure(string procedurename, DataParamCol parms, bool commit)
        {
            bool flag = true;
            base.ClearErrorMessage();
            if (commit)
            {
                this.TransactionBegin();
            }
            OracleCommand cmd = new OracleCommand(procedurename, this.dataConn, this.dbTransaction);
            try
            {
                cmd.CommandType = CommandType.StoredProcedure;
                if (parms != null)
                {
                    this.AddParms(cmd, parms);
                }
                cmd.ExecuteNonQuery();
                if (base.recordChangeSQL && !this.SaveChangeSQL(procedurename, parms))
                {
                    throw new DataException("记录SQL执行语句不成功!\r\n " + procedurename);
                }
                if (commit)
                {
                    base.TransactionCommit();
                }
                if (parms != null)
                {
                    base.GetParmsValue(cmd, parms);
                }
            }
            catch (Exception exception)
            {
                if (commit)
                {
                    base.TransactionRollback();
                }
                base.errorMessage.Append(exception.Message);
                flag = false;
            }
            return flag;
        }

        public override bool ExecuteScalar(string commandtext, DataParamCol parms, ref object obj, bool close_db)
        {
            bool flag = true;
            base.ClearErrorMessage();
            try
            {
                if ((base.transactionID == -1) && !this.IsOpen)
                {
                    this.Open();
                }
                OracleCommand cmd = new OracleCommand(commandtext, this.dataConn);
                if (this.dbTransaction != null)
                {
                    cmd.Transaction = this.dbTransaction;
                }
                if (parms != null)
                {
                    this.AddParms(cmd, parms);
                }
                obj = cmd.ExecuteScalar();
            }
            catch (Exception exception)
            {
                flag = false;
                base.errorMessage.Append(exception.Message);
            }
            finally
            {
                if ((base.autoClose && close_db) && (this.dbTransaction == null))
                {
                    this.DBClose();
                }
            }
            return flag;
        }

        public override int ExecuteSql(string commandtext, DataParamCol parms, int nrows, bool commit)
        {
            int num;
            base.ClearErrorMessage();
            if (commit)
            {
                this.TransactionBegin();
            }
            OracleCommand cmd = new OracleCommand(commandtext, this.dataConn, this.dbTransaction);
            try
            {
                Logger logger = new Logger("MM.Common.DBBase.DbOracleData");
                logger.Exp("Retrieve:" + commandtext);
                foreach (DataParam param in parms)
                {
                    if (param.Value != null)
                    {
                        logger.Exp(param.Name + ":" + param.Value);
                    }
                }
                if (parms != null)
                {
                    this.AddParms(cmd, parms);
                }
                num = cmd.ExecuteNonQuery();
                if ((nrows > 0) && (num != nrows))
                {
                    throw new DataException("执行作用的记录数与要求不一致\r\n " + commandtext);
                }
                if (base.recordChangeSQL && !this.SaveChangeSQL(commandtext, parms))
                {
                    throw new DataException("记录SQL执行语句不成功!\r\n " + commandtext);
                }
                if (commit)
                {
                    base.TransactionCommit();
                }
            }
            catch (Exception exception)
            {
                if (commit)
                {
                    base.TransactionRollback();
                }
                base.errorMessage.Append(exception.Message);
                num = -1;
                Logger logger2 = new Logger("MM.Common.DBBase.DbOracleData");
                logger2.Exp("ExecuteSql:" + commandtext + base.errorMessage);
                foreach (DataParam param2 in parms)
                {
                    if (param2.Value != null)
                    {
                        logger2.Exp(param2.Name + ":" + param2.Value);
                    }
                }
            }
            return num;
        }

        public override string GetDbDefault(string table_name, string column_name)
        {
            object obj2 = new object();
            string str = "";
            string commandtext = "SELECT F_GET_DB_DEFAULT(:tname ,:cname) FROM DUAL ";
            DataParamCol parms = new DataParamCol();
            parms.AddBatch(new object[] { "tname", table_name, "cname", column_name });
            if (base.ExecuteScalar(commandtext, parms, ref obj2))
            {
                str = obj2.ToString();
                if ((str.Length >= 2) && (str[0] == '\''))
                {
                    str = str.Substring(1, str.Length - 2);
                }
            }
            return str;
        }

        public override DateTime GetDBTime()
        {
            OracleCommand command = new OracleCommand("SELECT SYSDATE FROM DUAL", this.dataConn, this.dbTransaction);
            return (DateTime)command.ExecuteScalar();
        }

        protected OracleType GetDBType(string type)
        {
            OracleType varChar = (OracleType)0;
            varChar = OracleType.VarChar;
            try
            {
                switch (type)
                {
                    case "System.String":
                        return OracleType.VarChar;

                    case "System.Int32":
                        return OracleType.Int32;

                    case "System.Int16":
                        return OracleType.Int16;

                    case "System.Single":
                    case "System.Double":
                    case "System.Decimal":
                        return OracleType.Number;

                    case "System.DateTime":
                        return OracleType.DateTime;

                    case "System.Object":
                        return OracleType.Blob;

                    case "System.Boolean":
                        return OracleType.Cursor;
                }
                throw new DataException("不支持的参数类型: " + type.ToString());
            }
            catch
            {
            }
            return varChar;
        }

        protected override void GetSqlParmLen()
        {
            try
            {
                string commandtext = "SELECT DATA_LENGTH FROM USER_TAB_COLUMNS WHERE TABLE_NAME = :tname AND COLUMN_NAME = :cname";
                object obj2 = new object();
                DataParamCol parms = new DataParamCol();
                parms.Add("tname", "KTSYS_CHANGE_SQL");
                parms.Add("cname", "PARM");
                base.ExecuteScalar(commandtext, parms, ref obj2);
                if (obj2.GetType().Name == "Decimal")
                {
                    base.sqlParmLen = Convert.ToInt16(obj2);
                }
            }
            catch
            {
            }
        }

        protected override bool Open()
        {
            base.ClearErrorMessage();
            try
            {
                this.dataConn.Open();
                return true;
            }
            catch (Exception exception)
            {
                base.errorMessage.Append(exception.Message);
                return false;
            }
        }

        public override bool Open(string connectstring)
        {
            this.dataConn = new OracleConnection();
            this.dataConn.ConnectionString = connectstring;
            return this.Open();
        }

        public override bool Retrieve(string[] commandtexts, DataParamCol[] parms, ref DataTable[] dts, bool close_db)
        {
            bool flag = false;
            base.ClearErrorMessage();
            try
            {
                if ((base.transactionID == -1) && !this.IsOpen)
                {
                    this.Open();
                }
                for (int i = 0; i < commandtexts.Length; i++)
                {
                    OracleCommand cmd = new OracleCommand(commandtexts[i], this.dataConn);
                    if (this.dbTransaction != null)
                    {
                        cmd.Transaction = this.dbTransaction;
                    }
                    if ((parms.Length > i) && (parms[i] != null))
                    {
                        this.AddParms(cmd, parms[i]);
                    }
                    new OracleDataAdapter(cmd).Fill(dts[i]);
                }
                flag = true;
            }
            catch (Exception exception)
            {
                base.errorMessage.Append(exception.Message);
            }
            finally
            {
                if ((base.autoClose && close_db) && (this.dbTransaction == null))
                {
                    this.DBClose();
                }
            }
            return flag;
        }

        public override bool Retrieve(string commandtext, DataParamCol parm, ref DataTable dt, bool close_db)
        {
            bool flag = false;
            base.ClearErrorMessage();
            try
            {
                Logger logger = new Logger("MM.Common.DBBase.DbOracleData");
                logger.Exp("Retrieve:" + commandtext);
                if (parm != null)
                {
                    foreach (DataParam param in parm)
                    {
                        if (param.Value != null)
                        {
                            logger.Exp(param.Name + ":" + param.Value);
                        }
                    }
                }
                if ((base.transactionID == -1) && !this.IsOpen)
                {
                    this.Open();
                }
                OracleCommand cmd = new OracleCommand(commandtext, this.dataConn);
                if (this.dbTransaction != null)
                {
                    cmd.Transaction = this.dbTransaction;
                }
                if (parm != null)
                {
                    this.AddParms(cmd, parm);
                }
                new OracleDataAdapter(cmd).Fill(dt);
                flag = true;
            }
            catch (Exception exception)
            {
                base.errorMessage.Append(exception.Message);
                Logger logger2 = new Logger("MM.Common.DBBase.DbOracleData");
                logger2.Exp("Retrieve:" + commandtext + base.errorMessage);
                foreach (DataParam param2 in parm)
                {
                    if (param2.Value != null)
                    {
                        logger2.Exp(param2.Name + ":" + param2.Value);
                    }
                }
                return flag;
            }
            finally
            {
                if ((base.autoClose && close_db) && (this.dbTransaction == null))
                {
                    this.DBClose();
                }
            }
            return flag;
        }

        public override bool RetrieveProcedure(string procedure_name, DataParamCol parms, ref DataTable dt, bool close_db)
        {
            bool flag = true;
            base.ClearErrorMessage();
            try
            {
                if ((base.transactionID == -1) && !this.IsOpen)
                {
                    this.Open();
                }
                OracleCommand selectCommand = new OracleCommand(procedure_name, this.dataConn);
                OracleDataAdapter adapter = new OracleDataAdapter(selectCommand);
                if (this.dbTransaction != null)
                {
                    selectCommand.Transaction = this.dbTransaction;
                }
                selectCommand.CommandType = CommandType.StoredProcedure;
                if (parms != null)
                {
                    this.AddParms(selectCommand, parms);
                }
                if (dt == null)
                {
                    dt = new DataTable();
                }
                adapter.Fill(dt);
                if (parms != null)
                {
                    base.GetParmsValue(selectCommand, parms);
                }
            }
            catch (Exception exception)
            {
                base.errorMessage.Append(exception.Message);
                flag = false;
            }
            finally
            {
                if ((base.autoClose && close_db) && (this.dbTransaction == null))
                {
                    this.DBClose();
                }
            }
            return flag;
        }

        protected override bool RollbackTransaction()
        {
            try
            {
                if (this.IsExistTransaction)
                {
                    this.dbTransaction.Rollback();
                }
                return true;
            }
            catch (Exception exception)
            {
                base.errorMessage.Append(exception.Message);
                return false;
            }
        }

        public override int RunSql(string[] commandtexts, DataParamCol[] parms, int[] nrows, bool commit)
        {
            int num = 0;
            base.ClearErrorMessage();
            if (commit)
            {
                this.TransactionBegin();
            }
            OracleCommand cmd = new OracleCommand
            {
                Connection = this.dataConn,
                Transaction = this.dbTransaction
            };
            try
            {
                for (int i = 0; i < commandtexts.Length; i++)
                {
                    num = i + 1;
                    cmd.CommandText = commandtexts[i];
                    if (((parms != null) && (parms.Length >= (i + 1))) && (parms[i] != null))
                    {
                        this.AddParms(cmd, parms[i]);
                    }
                    int num2 = cmd.ExecuteNonQuery();
                    if ((nrows[i] > 0) && (num2 != nrows[i]))
                    {
                        nrows[i] = num2;
                        throw new DataException("执行作用的记录数与要求不一致!");
                    }
                    if (base.recordChangeSQL)
                    {
                        DataParamCol parm = new DataParamCol();
                        if (((parms != null) && (parms.Length >= (i + 1))) && (parms[i] != null))
                        {
                            parm = parms[i];
                        }
                        if (!this.SaveChangeSQL(commandtexts[i], parm))
                        {
                            throw new DataException(base.ErrorMessage);
                        }
                    }
                    cmd.Parameters.Clear();
                }
                if (commit)
                {
                    base.TransactionCommit();
                }
                num = 0;
            }
            catch (Exception exception)
            {
                if (commit)
                {
                    base.TransactionRollback();
                }
                base.errorMessage.Append(exception.Message);
                base.errorMessage.Append("\r\n");
                base.errorMessage.Append(cmd.CommandText);
            }
            return num;
        }

        private bool SaveChangeSQL(string cmdtext, DataParamCol parm)
        {
            bool flag = true;
            DataParamCol col = new DataParamCol();
            StringBuilder builder = new StringBuilder();
            base.ClearErrorMessage();
            if (parm != null)
            {
                foreach (DataParam param in parm)
                {
                    string name = param.Value.GetType().Name;
                    if (name == "Byte[]")
                    {
                        col.Add(param);
                        builder.Append(":" + param.Name + "[BLOB]= ");
                    }
                    else
                    {
                        builder.Append(":" + param.Name + "[" + name + "]=" + param.Value.ToString() + " ");
                    }
                }
            }
            string str2 = builder.ToString();
            int length = str2.Length;
            for (int i = 0; i < str2.Length; i++)
            {
                if (str2[i] > '\x00ff')
                {
                    length++;
                }
            }
            try
            {
                OracleCommand command = new OracleCommand("INSERT INTO KTSYS_CHANGE_SQL" + base.tableOrder + " (TRANSACTION_NO ,TRANSACTION_ORDER ,SQL_TEXT ,PARM) VALUES (:t_no ,:t_order ,:sql_text ,:parm_value)", this.dataConn, this.dbTransaction);
                command.Parameters.AddWithValue("t_no", base.transactionID);
                command.Parameters.AddWithValue("t_order", base.transactionOrder);
                command.Parameters.AddWithValue("sql_text", cmdtext);
                if (length < base.sqlParmLen)
                {
                    command.Parameters.AddWithValue("parm_value", str2);
                    command.ExecuteNonQuery();
                }
                else
                {
                    byte[] bytes = Encoding.Unicode.GetBytes(str2);
                    int num3 = bytes.Length;
                    command.Parameters.AddWithValue("parm_value", num3.ToString() + ";" + length.ToString());
                    command.ExecuteNonQuery();
                    command = new OracleCommand("INSERT INTO KTSYS_CHANGE_SQL_PARM (TRANSACTION_NO ,TRANSACTION_ORDER ,PARM_BLOB) VALUES (:t_no ,:t_order ,:parm_blob)", this.dataConn, this.dbTransaction);
                    command.Parameters.AddWithValue("t_no", base.transactionID);
                    command.Parameters.AddWithValue("t_order", base.transactionOrder);
                    command.Parameters.AddWithValue("parm_blob", bytes);
                    command.ExecuteNonQuery();
                }
                if (col.Count > 0)
                {
                    command = new OracleCommand("INSERT INTO KTSYS_CHANGE_SQL_BLOB (TRANSACTION_NO ,TRANSACTION_ORDER ,PARM) VALUES (:t_no ,:t_order ,:parm_value)", this.dataConn, this.dbTransaction);
                    command.Parameters.AddWithValue("t_no", base.transactionID);
                    command.Parameters.AddWithValue("t_order", base.transactionOrder);
                    command.Parameters.AddWithValue("parm_value", col[0].Value);
                    command.ExecuteNonQuery();
                }
                base.transactionOrder++;
            }
            catch (Exception exception)
            {
                base.errorMessage.Append("保存SQL语句出错! \r\n");
                base.errorMessage.Append(exception.Message);
                flag = false;
            }
            return flag;
        }

        // Properties
        public override bool IsExistTransaction
        {
            get
            {
                return ((this.dbTransaction != null) && (this.dbTransaction.Connection != null));
            }
        }

        public override bool IsOpen
        {
            get
            {
                return ((this.dataConn != null) && (this.dataConn.State == ConnectionState.Open));
            }
        }
    }
}
